home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / ASSEMBLE / H279.ZIP / WASM223.ZIP / SLEEPERM.ASM < prev    next >
Assembly Source File  |  1990-10-05  |  27KB  |  957 lines

  1. ; SLEEPER, Monochrome Version
  2. ; by Eric Tauck
  3. ;
  4. ; This program is a TSR that automatically disables
  5. ; a monochrome adapter after a specified amount of
  6. ; time to prevent screen burn-in.
  7. ;
  8. ; IMPORTANT NOTE: I figured out how to enable and
  9. ; disable a monochrome adapter by hacking another
  10. ; program.  Since I don't have any formal
  11. ; documentation on how to perform monochrome
  12. ; blanking, I don't guarantee that this program
  13. ; will work with all monchrome adapters.  Beware
  14. ; that the monitor can be physically damaged by
  15. ; messing around with the adapter ports.
  16.  
  17.         UNUSED+
  18.         JUMP+
  19.  
  20.         jmp     start           ;jump to entry point
  21.  
  22. ;****************************************
  23. ; Resident Data
  24.  
  25. VER_HI  EQU     1               ;high version number
  26. VER_LO  EQU     30              ;low version number
  27.  
  28. SIGN1   EQU     0534CH          ;first part of signature
  29. SIGN2   EQU     04550H          ;second part of signature
  30.  
  31. BIOSEG  EQU     0040H           ;BIOS data area segment
  32. BIOSHF  EQU     0017H           ;BIOS shift bits
  33. SMASK   EQU     00001111B       ;hot key shift mask
  34. SHIFT   EQU     00001100B       ;hot key shift bits (CONTROL + ALTERNATE)
  35.  
  36. func    DB      ?               ;keyboard function number
  37.  
  38. ;--- original interrupt handlers
  39.  
  40. int_09  LABEL   DWORD   ;old interrupt 9
  41.         DW      ?
  42.         DW      ?
  43.  
  44. int_16  LABEL   DWORD   ;old interrupt 16
  45.         DW      ?
  46.         DW      ?
  47.  
  48. int_1C  LABEL   DWORD   ;old interrupt 1C
  49.         DW      ?
  50.         DW      ?
  51.  
  52. int_21  LABEL   DWORD   ;old interrupt 21
  53.         DW      ?
  54.         DW      ?
  55.  
  56. ;--- flags
  57.  
  58. FIXED   EQU     0001H   ;video state fixed
  59. DISPL   EQU     0002H   ;video displayed
  60. FORCE   EQU     0004H   ;forced timeout
  61. flags   DW      0000H   ;current flag settings
  62.  
  63. ;--- timer data
  64.  
  65. ticks   DW      5460    ;count value (5 min * 60 sec/min * 18.2 tic/sec)
  66. timer   DW      ?       ;timer value
  67.  
  68. ;--- resident functions
  69.  
  70. NOTHING EQU     0       ;do nothing
  71. RESET   EQU     1       ;reset timer
  72. SHOW    EQU     2       ;screen on
  73. HIDE    EQU     3       ;screen off
  74. TIME    EQU     4       ;force timeout
  75.  
  76. functab LABEL   WORD                    ;resident function table
  77.         DW      OFFSET dummy
  78.         DW      OFFSET screen_reset
  79.         DW      OFFSET screen_on
  80.         DW      OFFSET screen_off
  81.         DW      OFFSET timeout
  82.  
  83. ;****************************************
  84. ; Resident Code
  85.  
  86. ;========================================
  87. ; Low level control.
  88.  
  89. ;--- reset timer
  90.  
  91. reset_timer PROC    NEAR
  92.         seg     cs
  93.         push    ticks           ;ticks on stack
  94.         seg     cs
  95.         pop     timer           ;load timer
  96.         ret
  97.         ENDP
  98.  
  99. ;--- turn off video
  100.  
  101. video_off PROC    NEAR
  102.         push    ax
  103.         push    dx
  104.         mov     dx, 3B8H
  105.         mov     al, 21H
  106.         out     dx, al
  107.         seg     cs
  108.         and     flags, NOT DISPL        ;clear flag
  109.         pop     dx
  110.         pop     ax
  111.         ret
  112.         ENDP
  113.  
  114. ;--- turn on video
  115.  
  116. video_on PROC    NEAR
  117.         push    ax
  118.         push    dx
  119.         mov     dx, 3B8H
  120.         mov     al, 29H
  121.         out     dx, al
  122.         seg     cs
  123.         or      flags, DISPL    ;set flag
  124.         pop     dx
  125.         pop     ax
  126.         ret
  127.         ENDP
  128.  
  129. ;========================================
  130. ; Screen functions.
  131.  
  132. ;--- reset screen timer
  133.  
  134. screen_reset PROC NEAR
  135.         seg     cs
  136.         and     flags, NOT FIXED ;clear fixed flag
  137.         call    reset_timer     ;reset timer
  138.         seg     cs
  139.         test    flags, DISPL    ;check if screen on
  140.         jnz     novon
  141.         call    video_on        ;turn on screen
  142. novon   ret
  143.         ENDP
  144.  
  145. ;--- force timeout
  146.  
  147. timeout PROC NEAR
  148.         seg     cs
  149.         and     flags, NOT FIXED ;clear fixed flag (reset)
  150.         seg     cs
  151.         or      flags, FORCE    ;set forced timeout flag
  152.         seg     cs
  153.         mov     timer, 18       ;set timer to two seconds
  154.         ret
  155.         ENDP
  156.  
  157. ;--- turn screen off
  158.  
  159. screen_off PROC NEAR
  160.         seg     cs
  161.         or      flags, FIXED    ;set fixed flag
  162.         seg     cs
  163.         mov     timer, 0        ;zero timer
  164.         call    video_off       ;turn off screen
  165.         ret
  166.         ENDP
  167.  
  168. ;--- screen on
  169.  
  170. screen_on PROC NEAR
  171.         seg     cs
  172.         or      flags, FIXED    ;set fixed flag
  173.         seg     cs
  174.         mov     timer, 0        ;zero timer
  175.         call    video_on        ;turn on screen
  176.         ret
  177.         ENDP
  178.  
  179. ;--- dummy function
  180.  
  181. dummy   PROC    NEAR
  182.         ret
  183.         ENDP
  184.  
  185. ;--- transfer to screen routine in BX
  186.  
  187. screen_func PROC NEAR
  188.         shl     bx                      ;convert number to offset
  189.         seg     cs
  190.         jmp     WORD [functab + bx]     ;branch to routine
  191.         ENDP
  192.  
  193. ;========================================
  194. ; Interrupt 09H handler.
  195.  
  196. key_han PROC    NEAR
  197.         seg     cs
  198.         test    flags, FIXED OR FORCE   ;check if fixed state or forced timeout
  199.         jnz     kdone
  200.         call    screen_reset    ;reset timer and screen
  201. kdone   seg     cs
  202.         jmp     int_09          ;branch to old keyboard handler
  203.         ENDP
  204.  
  205. ;========================================
  206. ; Check for a hotkey and pass command
  207. ; to resident sleeper.  NOTE: all the
  208. ; flags except CY are preserved.
  209. ;
  210. ; In: AH= scan code.
  211. ;
  212. ; Out: CY= set if hotkey pressed,
  213. ;      cleared if not.
  214.  
  215. key_check PROC  NEAR
  216.         pushf
  217.         push    ax
  218.         push    bx
  219.  
  220. ;--- check scan code
  221.  
  222.         mov     bx, RESET
  223.         cmp     ah, 19          ;R - reset timer
  224.         je      kshft
  225.         mov     bx, SHOW
  226.         cmp     ah, 47          ;V - visible screen
  227.         je      kshft
  228.         mov     bx, HIDE
  229.         cmp     ah, 35          ;H - hidden screen
  230.         je      kshft
  231.         mov     bx, TIME
  232.         cmp     ah, 20          ;T - force timeout
  233.         je      kshft
  234.  
  235. kcdone  pop     bx
  236.         pop     ax
  237.         popf
  238.         clc
  239.         ret
  240.  
  241. ;--- check shift state
  242.  
  243. kshft   push    ds
  244.         mov     ax, BIOSEG      ;data area segment
  245.         mov     ds, ax
  246.         mov     al, [BIOSHF]    ;load first shift byte
  247.         pop     ds
  248.  
  249.         and     al, SMASK       ;mask bits
  250.         cmp     al, SHIFT       ;check if proper shift
  251.         jne     kcdone          ;exit if not
  252.  
  253. ;--- execute resident function
  254.  
  255.         call    screen_func     ;execute screen function
  256.  
  257.         pop     bx
  258.         pop     ax
  259.         popf
  260.         stc
  261.         ret
  262.         ENDP
  263.  
  264. ;========================================
  265. ; Interrupt 16H handler.
  266.  
  267. key2_han PROC   NEAR
  268.         seg     cs
  269.         mov     func, ah        ;save function number
  270.  
  271.         cmp     ah, 0           ;check if fetch key
  272.         je      k2fet
  273.         cmp     ah, 10H         ;check if fetch extended key
  274.         je      k2fet
  275.         cmp     ah, 1           ;check if keyboard status
  276.         je      k2stat
  277.         cmp     ah, 11H         ;check if extended keyboard status
  278.         je      k2stat
  279.         seg     cs
  280.         jmp     int_16          ;branch to original keyboard handler
  281.  
  282. ;--- fetch keystroke
  283.  
  284. k2fet1  seg     cs
  285.         mov     ah, func        ;load function
  286.  
  287. k2fet   pushf
  288.         seg     cs
  289.         call    int_16          ;call keyboard handler
  290.         call    key_check       ;check for hotkey
  291.         jc      k2fet1          ;loop back if so
  292.  
  293.         iret
  294.  
  295. ;--- keyboard status
  296.  
  297. k2stat1 sub     ah, ah          ;fetch key function
  298.         pushf
  299.         seg     cs
  300.         call    int_16          ;call keyboard handler
  301.         seg     cs
  302.         mov     ah, func        ;reload function
  303.         
  304. k2stat  pushf
  305.         seg     cs
  306.         call    int_16          ;call keyboard handler
  307.         jz      k2e2            ;exit if no key
  308.  
  309.         call    key_check       ;check for hotkey
  310.         jc      k2stat1         ;loop back if so
  311.  
  312. k2e2    retf    2               ;return with flags
  313.         ENDP
  314.  
  315. ;========================================
  316. ; Interrupt 1CH handler.
  317.  
  318. tic_han PROC    NEAR
  319.         seg     cs
  320.         cmp     timer, 0                ;check if timer zero
  321.         je      tdone                   ;done if so
  322.  
  323.         seg     cs
  324.         dec     timer                   ;decrement timer
  325.         jnz     tdone
  326.         call    video_off               ;turn off screen
  327.         seg     cs
  328.         and     flags, NOT FORCE        ;clear forced flag
  329.  
  330. tdone   seg     cs
  331.         jmp     int_1C                  ;branch to old timer handler
  332.         ENDP
  333.  
  334. ;========================================
  335. ; Interrupt 21H handler.
  336.  
  337. dos_han PROC   NEAR
  338.         cmp     ah, 2Bh         ;check set date function
  339.         jne     ddone
  340.         cmp     cx, SIGN1       ;check if first signature matches
  341.         jne     ddone
  342.         cmp     dx, SIGN2       ;check if second signature matches
  343.         jne     ddone
  344.  
  345. ;--- external query
  346.  
  347.         call    screen_func     ;execute screen function in BX
  348.         sub     al, al          ;clear error
  349.         mov     dx, cs          ;return segment
  350.         iret                    ;exit
  351.  
  352. ;--- branch to old DOS
  353.  
  354. ddone   seg     cs
  355.         jmp     int_21          ;branch to dos handler
  356.         ENDP
  357.  
  358. ;========================================
  359. ; End of resident code/data.
  360.  
  361. end_res LABEL  NEAR             ;label marking end
  362.  
  363. ;****************************************
  364. ; Transient Data
  365.  
  366. ENVIRO  EQU    002CH            ;offset of environtment in PSP
  367. COMLINE EQU    0081H            ;start of command line characters
  368.  
  369. ;--- option table
  370.  
  371. OPT_HELP        EQU     0       ;request help
  372. OPT_INSTALL     EQU     1       ;install
  373. OPT_UNINSTALL   EQU     2       ;uninstall
  374. OPT_RESET       EQU     3       ;reset timer
  375. OPT_SHOW        EQU     4       ;force visible
  376. OPT_HIDE        EQU     5       ;force hidden
  377. OPT_TICKS       EQU     6       ;set ticks
  378. OPT_TIMEOUT     EQU     7       ;force timeout
  379.  
  380. opttab  LABEL   WORD                    ;option routine table
  381.         DW      OFFSET help
  382.         DW      OFFSET install
  383.         DW      OFFSET remove
  384.         DW      OFFSET send_reset
  385.         DW      OFFSET send_show
  386.         DW      OFFSET send_hide
  387.         DW      OFFSET send_ticks
  388.         DW      OFFSET send_timeout
  389.  
  390. ;--- messages
  391.  
  392. banner  DB      13,10,'SLEEPER  Mono Version '
  393.         DB      VER_HI+'0', '.', (VER_LO/10)+'0', (VER_LO\10)+'0'
  394.         DB      'A  Eric Tauck  8/2/1990',13,10,'$'
  395.  
  396. mes1a   DB      'Sleeper installed with timer = ','$'
  397. mes1b   DB      ' ticks',13,10,'$'
  398. mes2    DB      'Error in options, run "SLEEPER ?" for help',13,10,'$'
  399. mes3    DB      'Cannot uninstall Sleeper',13,10,'$'
  400. mes4    DB      'Sleeper removed from memory',13,10,'$'
  401. mes5    DB      'Sleeper must be installed first',13,10,'$'
  402. mes6    DB      'Sleeper already installed',13,10,'$'
  403. mes7a   DB      'Sleeper reset with timer = ','$'
  404. mes7b   DB      ' ticks',13,10,'$'
  405. mes8    DB      'Sleeper timer reset',13,10,'$'
  406. mes9    DB      'Screen forced visible',13,10,'$'
  407. mes10   DB      'Screen forced hidden',13,10,'$'
  408. mes11   DB      'Forced timeout',13,10,'$'
  409.  
  410. ;--- help message
  411.  
  412. hmes    LABEL   BYTE
  413.   DB 13,10
  414.   DB 'Installation Options:',13,10
  415.   DB 13,10
  416.   DB '  SLEEPER       install with a default timer value of 5 minutes',13,10
  417.   DB '  SLEEPER nnn   install with a timer value of 1 to 3600 seconds',13,10
  418.   DB 13,10
  419.   DB 'Resident Options:',13,10
  420.   DB 13,10
  421.   DB '  SLEEPER v     force visible screen (also when not resident)',13,10
  422.   DB '  SLEEPER h     force hidden screen (also when not resident)',13,10
  423.   DB '  SLEEPER t     force timeout',13,10
  424.   DB '  SLEEPER r     reset timer',13,10
  425.   DB '  SLEEPER nnn   reset timer with a value of 1 to 3600 seconds',13,10
  426.   DB '  SLEEPER u     uninstall',13,10
  427.   DB 13,10
  428.   DB 'Keyboard Commands:',13,10
  429.   DB 13,10
  430.   DB '  ALT-CTL-V     force visible screen',13,10
  431.   DB '  ALT-CTL-H     force hidden screen',13,10
  432.   DB '  ALT-CTL-T     force timeout',13,10
  433.   DB '  ALT-CTL-R     reset timer ',13,10
  434.   DB '$'
  435.  
  436. ;****************************************
  437. ; Transient Code
  438.  
  439. ;========================================
  440. ; Macro to display a $ terminated string
  441.  
  442. display MACRO   str
  443.         mov     ah, 9           ;display function
  444.         mov     dx, OFFSET str  ;load address
  445.         int     21H             ;execute
  446.         ENDM
  447.  
  448. ;========================================
  449. ; Display the number in AX.
  450.  
  451. number  PROC    NEAR
  452.         mov     bx, 10          ;base
  453.         sub     cx, cx          ;digit count
  454.  
  455. ;--- determine decimal digits
  456.  
  457. numeval sub     dx, dx          ;zero for divide
  458.         div     ax, bx          ;divide by base
  459.         push    dx              ;save digit on stack
  460.         inc     cx              ;increment digit count
  461.         or      ax, ax          ;check if anything left
  462.         jnz     numeval         ;loop back if so
  463.  
  464. ;--- display number
  465.  
  466. numdisp pop     dx              ;restore value
  467.         add     dl, '0'         ;convert to ASCII
  468.         mov     ah, 2           ;display function
  469.         int     21H             ;execute
  470.         loop    numdisp         ;loop for each digit
  471.  
  472.         ret
  473.         ENDP
  474.  
  475. ;========================================
  476. ; Call resident sleeper.
  477. ;
  478. ; In: BX= resident command.
  479. ;
  480. ; Out: DX= resident data segment; CY=
  481. ;      set if error (not resident).
  482.  
  483. resident PROC   NEAR
  484.         mov     ah, 2Bh         ;set date function
  485.         mov     cx, SIGN1       ;signature one
  486.         mov     dx, SIGN2       ;signature two
  487.         int     21H             ;execute
  488.         sub     al, 1           ;subtract (use SUB to set CY flag)
  489.         cmc                     ;set carry on error
  490.         ret
  491.         ENDP
  492.  
  493. ;========================================
  494. ; Process command line.
  495. ;
  496. ; Out: BX= option number; CY= set if
  497. ;      error.
  498.  
  499. options PROC    NEAR
  500.         cld
  501.  
  502. ;--- skip delimiters
  503.  
  504.         mov     si, COMLINE     ;start of command line
  505.         mov     bx, OPT_INSTALL
  506.  
  507. skdel   lodsb                   ;load character
  508.         cmp     al, 13          ;check if end of line
  509.         je      optok           ;exit if so
  510.         cmp     al, ' '         ;check if delimiter
  511.         jbe     skdel           ;loop back if so
  512.  
  513. ;--- check for standard options
  514.  
  515.         mov     dl, al          ;save character
  516.         or      al, 20H         ;convert to lower-case
  517.         mov     bx, OPT_RESET
  518.         cmp     al, 'r'
  519.         je      optok
  520.         mov     bx, OPT_SHOW
  521.         cmp     al, 'v'
  522.         je      optok
  523.         mov     bx, OPT_HIDE
  524.         cmp     al, 'h'
  525.         je      optok
  526.         mov     bx, OPT_UNINSTALL
  527.         cmp     al, 'u'
  528.         je      optok
  529.         mov     bx, OPT_HELP
  530.         cmp     al, '?'
  531.         je      optok
  532.         mov     bx, OPT_TIMEOUT
  533.         cmp     al, 't'
  534.         je      optok
  535.  
  536. ;--- convert number
  537.  
  538.         mov     bx, 10          ;base
  539.         sub     cx, cx          ;zero total
  540.         mov     al, dl          ;restore character
  541.  
  542. evall   sub     al, '0'         ;convert to value
  543.         cmp     al, 9           ;check if out of range
  544.         ja      opterr          ;jump if so
  545.  
  546.         sub     ah, ah
  547.         xchg    ax, cx          ;total in AX, digit value in CX
  548.         mul     ax, bx          ;total times base
  549.         add     cx, ax          ;new total
  550.  
  551.         lodsb                   ;load next character
  552.         cmp     al, ' '         ;check if delimiter
  553.         ja      evall           ;loop back if not
  554.  
  555.         mov     ax, 18          ;18/ticks per second
  556.         mul     cx              ;convert
  557.         or      dx, dx          ;check if too big
  558.         jnz     opterr          ;jump if so
  559.         push    ax
  560.         mov     ax, 5           ;plus .2/ticks per sec
  561.         xchg    ax, cx
  562.         div     ax, cx          ;for every 5, add one more
  563.         pop     dx
  564.         add     dx, ax          ;total ticks
  565.         jc      opterr          ;jump if too many
  566.         mov     ticks, dx       ;save ticks
  567.         mov     bx, OPT_TICKS   ;return function
  568.  
  569. ;--- done
  570.  
  571. optok   clc
  572.         ret
  573.  
  574. ;--- error
  575.  
  576. opterr  display mes2    ;show error message
  577.         stc
  578.         ret
  579.         ENDP
  580.  
  581. ;========================================
  582. ; Display help screen.
  583. ;
  584. ; Out: AL= termination code.
  585.  
  586. help    PROC    NEAR
  587.         display hmes    ;display help text
  588.         sub     al, al  ;no error
  589.         ret
  590.         ENDP
  591.  
  592. ;========================================
  593. ; Install in memory.
  594. ;
  595. ; Out: AL= termination code (only if
  596. ;      failure).
  597.  
  598. install PROC    NEAR
  599.  
  600. ;--- check if already installed
  601.  
  602.         mov     bx, NOTHING     ;no resident operation
  603.         call    resident        ;link to resident version
  604.         jc      noierr          ;jump if okay
  605.         display mes6            ;display error message
  606.         mov     al, -1          ;return error code
  607.         ret
  608.  
  609. ;--- start installation
  610.  
  611. noierr  call    reset_timer     ;reset timer
  612.  
  613. ;--- display message
  614.  
  615.         display mes1a           ;first part
  616.         mov     ax, ticks       ;load timer value
  617.         call    number          ;display
  618.         display mes1b           ;second part
  619.  
  620. ;--- save keyboard interrupt 9
  621.  
  622.         mov     ax, 3509H               ;get keyboard interrupt
  623.         int     21H                     ;execute
  624.         mov     WORD int_09, bx         ;save offset
  625.         mov     WORD int_09+2, es       ;save segment
  626.  
  627. ;--- install keyboard interrupt 9
  628.  
  629.         mov     ax, 2509H               ;set keyboard interrupt
  630.         mov     dx, OFFSET key_han      ;keyboard handler
  631.         int     21H                     ;execute
  632.  
  633. ;--- save timer interrupt 1C
  634.  
  635.         mov     ax, 351CH               ;get keyboard interrupt
  636.         int     21H                     ;execute
  637.         mov     WORD int_1C, bx         ;save offset
  638.         mov     WORD int_1C+2, es       ;save segment
  639.  
  640. ;--- install timer interrupt 1C
  641.  
  642.         mov     ax, 251CH               ;set interrupt 1C
  643.         mov     dx, OFFSET tic_han      ;timer tick handler
  644.         int     21H                     ;execute
  645.         call    reset_timer             ;reset timer
  646.  
  647. ;--- save keyboard fetch interrupt 16
  648.  
  649.         mov     ax, 3516H               ;get keyboard interrupt
  650.         int     21H                     ;execute
  651.         mov     WORD int_16, bx         ;save offset
  652.         mov     WORD int_16+2, es       ;save segment
  653.  
  654. ;--- install keyboard fetch interrupt 16
  655.  
  656.         mov     ax, 2516H               ;set interrupt 16
  657.         mov     dx, OFFSET key2_han     ;keyboard fetch handler
  658.         int     21H                     ;execute
  659.  
  660. ;--- save DOS interrupt 21
  661.  
  662.         mov     ax, 3521H               ;get keyboard interrupt
  663.         int     21H                     ;execute
  664.         mov     WORD int_21, bx         ;save offset
  665.         mov     WORD int_21+2, es       ;save segment
  666.  
  667. ;--- install DOS interrupt 21
  668.  
  669.         mov     ax, 2521H               ;set interrupt 21
  670.         mov     dx, OFFSET dos_han      ;DOS handler
  671.         int     21H                     ;execute
  672.  
  673. ;--- install
  674.  
  675.         mov     dx, OFFSET end_res      ;end of resident code
  676.         mov     cl, 4
  677.         shr     dx, cl                  ;convert to paragraph
  678.         inc     dx                      ;round up, paragraphs to reserve
  679.  
  680.         mov     ax, 3100H       ;resident-terminate with exit code 0
  681.         int     21H             ;execute
  682.         ENDP
  683.  
  684. ;========================================
  685. ; Remove from memory.
  686. ;
  687. ; Out: AL= termination code.
  688.  
  689. remove  PROC    NEAR
  690.  
  691. ;--- check if installed
  692.  
  693.         mov     bx, NOTHING     ;no resident operation
  694.         call    resident        ;link to resident version
  695.         jnc     norerr          ;jump if okay
  696.         display mes5            ;display error message
  697.         mov     al, -1          ;return error code
  698.         ret
  699.  
  700. ;--- start removal
  701.  
  702. norerr  push    ds
  703.         mov     ds, dx          ;switch to resident data segment
  704.  
  705. ;=== verify vectors
  706.  
  707.         mov     cx, ds
  708.  
  709. ;--- verify interrupt 9
  710.  
  711.         mov     ax, 3509H               ;get interrupt
  712.         int     21H                     ;execute
  713.         cmp     bx, OFFSET key_han      ;check offset
  714.         jne     verr
  715.         mov     ax, es
  716.         cmp     ax, cx                  ;check segment
  717.         jne     verr
  718.  
  719. ;--- verify interrupt 1C
  720.  
  721.         mov     ax, 351CH               ;get interrupt
  722.         int     21H                     ;execute
  723.         cmp     bx, OFFSET tic_han      ;check offset
  724.         jne     verr
  725.         mov     ax, es
  726.         cmp     ax, cx                  ;check segment
  727.         jne     verr
  728.  
  729. ;--- verify interrupt 16
  730.  
  731.         mov     ax, 3516H               ;get interrupt
  732.         int     21H                     ;execute
  733.         cmp     bx, OFFSET key2_han     ;check offset
  734.         jne     verr
  735.         mov     ax, es
  736.         cmp     ax, cx                  ;check segment
  737.         jne     verr
  738.  
  739. ;--- verify interrupt 21
  740.  
  741.         mov     ax, 3521H               ;get interrupt
  742.         int     21H                     ;execute
  743.         cmp     bx, OFFSET dos_han      ;check offset
  744.         jne     verr
  745.         mov     ax, es
  746.         cmp     ax, cx                  ;check segment
  747.         jne     verr
  748.         jmps    unhook
  749.  
  750. ;--- error
  751.  
  752. verr    pop     ds
  753.         display mes3            ;display message
  754.         mov     al, -1          ;error code
  755.         ret
  756.  
  757. ;=== unhook interrupts
  758.  
  759. unhook  push    ds              ;save resident segment
  760.         push    ds
  761.         pop     es              ;transfer resident segment to ES
  762.  
  763. ;--- unhook 9
  764.  
  765.         mov     ax, 2509H               ;set interrupt function
  766.         seg     es
  767.         mov     dx, WORD int_09         ;offset
  768.         seg     es
  769.         mov     ds, WORD int_09+2       ;segment
  770.         int     21H                     ;execute
  771.  
  772. ;--- unhook 16
  773.  
  774.         mov     ax, 2516H               ;set interrupt function
  775.         seg     es
  776.         mov     dx, WORD int_16         ;offset
  777.         seg     es
  778.         mov     ds, WORD int_16+2       ;segment
  779.         int     21H                     ;execute
  780.  
  781. ;--- unhook 1C
  782.  
  783.         mov     ax, 251CH               ;set interrupt function
  784.         seg     es
  785.         mov     dx, WORD int_1C         ;offset
  786.         seg     es
  787.         mov     ds, WORD int_1C+2       ;segment
  788.         int     21H                     ;execute
  789.  
  790. ;--- unhook 21
  791.  
  792.         mov     ax, 2521H               ;set interrupt function
  793.         seg     es
  794.         mov     dx, WORD int_21         ;offset
  795.         seg     es
  796.         mov     ds, WORD int_21+2       ;segment
  797.         int     21H                     ;execute
  798.  
  799.         pop     ds              ;restore resident segment
  800.  
  801. ;=== release memory
  802.  
  803. ;--- release environment
  804.  
  805.         mov     ax, [ENVIRO]    ;load environment segment
  806.         or      ax, ax          ;check if any
  807.         jz      noenv
  808.         mov     es, ax
  809.         mov     ah, 49H         ;release memory function
  810.         int     21H             ;execute
  811.  
  812. ;--- release code
  813.  
  814. noenv   push    ds
  815.         pop     es
  816.         mov     ah, 49H         ;release memory function
  817.         int     21H             ;execute
  818.  
  819.         pop     ds              ;restore local DS
  820.  
  821.         display mes4            ;display message
  822.         sub     al, al          ;no error
  823.         ret
  824.         ENDP
  825.  
  826. ;========================================
  827. ; Reset resident sleeper.
  828.  
  829. send_reset PROC NEAR
  830.         mov     bx, RESET       ;command
  831.         call    resident        ;send to resident sleeper
  832.         jc      sreserr
  833.  
  834. ;--- success
  835.  
  836.         display mes8            ;message
  837.         mov     al, 0           ;no error
  838.         ret
  839.  
  840. ;--- error
  841.  
  842. sreserr display mes5            ;error message
  843.         mov     al, -1          ;error code
  844.         ret
  845.         ENDP
  846.  
  847. ;========================================
  848. ; Force a timeout.
  849.  
  850. send_timeout PROC NEAR
  851.         mov     bx, TIME        ;command
  852.         call    resident        ;send to resident sleeper
  853.         jc      stimerr
  854.  
  855. ;--- success
  856.  
  857.         display mes11           ;message
  858.         mov     al, 0           ;no error
  859.         ret
  860.  
  861. ;--- error
  862.  
  863. stimerr display mes5            ;error message
  864.         mov     al, -1          ;error code
  865.         ret
  866.         ENDP
  867.  
  868. ;========================================
  869. ; Show screen.
  870.  
  871. send_show PROC NEAR
  872.         mov     bx, SHOW        ;command
  873.         call    resident        ;send to resident sleeper
  874.         jnc     sshook
  875.  
  876. ;--- turn on screen
  877.  
  878.         call    video_on        ;turn on video
  879.  
  880. ;--- done
  881.  
  882. sshook  display mes9            ;message
  883.         mov     al, 0           ;no error
  884.         ret
  885.         ENDP
  886.  
  887. ;========================================
  888. ; Hide screen.
  889.  
  890. send_hide PROC NEAR
  891.         mov     bx, HIDE        ;command
  892.         call    resident        ;send to resident sleeper
  893.         jnc     shidok
  894.  
  895. ;--- turn off screen
  896.  
  897.         call    video_off       ;turn off video
  898.  
  899. ;--- done
  900.  
  901. shidok  display mes10           ;message
  902.         mov     al, 0           ;no error
  903.         ret
  904.         ENDP
  905.  
  906. ;========================================
  907. ; Set number of ticks in resident
  908. ; sleeper.
  909.  
  910. send_ticks PROC NEAR
  911.  
  912. ;--- check if installed
  913.  
  914.         mov     bx, NOTHING     ;no resident operation
  915.         call    resident        ;link to resident version
  916.         jc      ticerr          ;jump if not installed
  917.  
  918. ;--- modify resident sleeper
  919.  
  920.         mov     ax, ticks       ;load local tick count
  921.         push    ds
  922.         mov     ds, dx          ;switch to resident segment
  923.         mov     ticks, ax       ;set new tick count
  924.         pop     ds
  925.         mov     bx, RESET       ;command
  926.         call    resident        ;send to resident sleeper
  927.  
  928. ;--- display message
  929.  
  930.         display mes7a           ;first part
  931.         mov     ax, ticks       ;load timer value
  932.         call    number          ;display
  933.         display mes7b           ;second part
  934.  
  935.         mov     al, 0           ;no error
  936.         ret
  937.  
  938. ;--- goto install
  939.  
  940. ticerr  jmp     install         ;goto install
  941.         ENDP
  942.  
  943. ;****************************************
  944. ; Program entry point.
  945.  
  946. start   display banner                  ;display banner
  947.         call    options                 ;parse command line
  948.         mov     al, -1                  ;error code if parameter error
  949.         jc      term                    ;jump if error
  950.         shl     bx                      ;adjust option number to offset
  951.         call    WORD [opttab + bx]      ;call option routine
  952.  
  953. ;--- terminate, result code in AL
  954.  
  955. term    mov     ah, 4CH         ;exit function
  956.         int     21H             ;execute
  957.